﻿using UnityEngine;
using System;
using System.Linq;
using System.Collections;

using Hont;

namespace Hont.C2UTool
{
    public class StaticInfoGeneralAnalyzer : IC2UStaticInfoAnalyzer
    {
        public int Priority { get { return 1; } }

        public bool CanSlover(string componentName)
        {
            return true;
        }

        public C2UStructs.StaticInfoArgumentStruct[] Analyze(string gameObjectPath, string componentName, string argumentInfoStr)
        {
            C2UStructs.StaticInfoArgumentStruct[] result = null;

            var argumentsStrArr = argumentInfoStr.Split('&');
            if (string.IsNullOrEmpty(argumentsStrArr[0])) argumentsStrArr = new string[0];
            result = new C2UStructs.StaticInfoArgumentStruct[argumentsStrArr.Length];

            for (int i = 0; i < argumentsStrArr.Length; i++)
            {
                var arg = C2UUtility.SplitEx(argumentsStrArr[i], '@', ':');

                var value = new C2UStructs.StaticInfoArgumentStruct();
                value.FieldName = arg[0][1];//field name
                var valueStr = C2UUtility.SecurityStringDecode(arg[2][1]);

                switch (arg[1][1])//type
                {
                    case "int":
                        value.Value = int.Parse(valueStr);
                        break;

                    case "float":
                        value.Value = float.Parse(valueStr);
                        break;

                    case "bool":
                        value.Value = valueStr == "1" ? true : false;
                        break;

                    case "string":
                        value.Value = valueStr;
                        break;

                    case "color":
                        var colorArr = valueStr.TrimStart("Vector(".ToCharArray()).TrimEnd(')').Split(',');
                        value.Value = new Color(float.Parse(colorArr[0]), float.Parse(colorArr[1]), float.Parse(colorArr[2]));
                        break;

                    case "vector":
                        var vectorArr = valueStr.TrimStart("Vector(".ToCharArray()).TrimEnd(')').Split(',');
                        value.Value = new Vector3(float.Parse(vectorArr[0]), float.Parse(vectorArr[1]), float.Parse(vectorArr[2]));
                        break;
                }
                result[i] = value;
            }

            return result;
        }

        public void ApplyToTarget(C2UStructs.StaticInfoStruct info, GameObject targetObject)
        {
            switch (info.ComponentName)
            {
                case "UnityEngine.GameObject"://The special type
                    var activeInfo = info.Values.FirstOrDefault(m => m.FieldName == "active");
                    if (activeInfo != null)
                    {
                        targetObject.SetActive((bool)activeInfo.Value);
                    }

                    break;

                default:
                    Component component = null;
                    var tmp = C2UUtility.GetRuntimeType(info.ComponentName);

                    if (tmp == null)
                        throw new NullReferenceException("Not found runtime type: " + info.ComponentName);

                    component = targetObject.AddComponent(tmp);

                    if (info.Values.Length > 0)
                    {
                        var fields = C2UUtility.GetObjectPublicFields(component);

                        for (int i = 0; i < info.Values.Length; i++)
                        {
                            var field = info.Values[i];

                            var targetField = fields.FirstOrDefault(m => m.Name == field.FieldName);
                            if (targetField == null) continue;

                            targetField.SetValue(component, field.Value);

                            if (targetField.FieldType == typeof(UnityEngine.Color))
                            {
                                var color = (UnityEngine.Color)targetField.GetValue(component);
                                color.a = 1;
                                targetField.SetValue(component, color);
                            }//Color type correction.
                        }
                    }

                    break;
            }
        }
    }
}